package com.borqsprocessmanager;

import java.util.ArrayList;
import java.util.List;

import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.Notification;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.os.IBinder;
import android.os.RemoteException;

import com.borqsprocessmanager.db.DBProvider.ActionTable;
import com.borqsprocessmanager.db.DBProvider.WhiteListTable;
import com.borqsprocessmanager.info.ActionMapInfo;
import com.borqsprocessmanager.info.BaseBatteryAlsInfo;
import com.borqsprocessmanager.info.BatteryTaskInfo;
import com.borqsprocessmanager.info.ProcessStatsInfo;
import com.borqsprocessmanager.info.ReceiverProcessInfo;
import com.borqsprocessmanager.info.WhiteMapMapInfo;
import com.borqsprocessmanager.interfaces.INetStateChanged;
import com.borqsprocessmanager.interfaces.IReciverCallback;
import com.borqsprocessmanager.receiver.AudioChangedReceiver;
import com.borqsprocessmanager.receiver.BatteryChangedReceiver;
import com.borqsprocessmanager.receiver.ConnectionChangeReceiver;
import com.borqsprocessmanager.receiver.PackageChangedReceiver;
import com.borqsprocessmanager.receiver.ScreenAndConChangedReceiver;
import com.borqsprocessmanager.receiver.TelephonChangedReceiver;
import com.borqsprocessmanager.sample.NetWorkSampleMoudle;
import com.borqsprocessmanager.sample.ProcessPowerModule;
import com.borqsprocessmanager.sample.SignalChangedModule;
import com.borqsprocessmanager.util.CPUFreqSetting;
import com.borqsprocessmanager.util.Log;
import com.borqsprocessmanager.util.PreferencesUtil;

public class BatteryManagerService extends Service implements IReciverCallback,
        INetStateChanged {
    private final String TAG = "BatteryManagerService";

    /**
     * 判断系统状态接口，是否usb连接，屏幕关闭等
     * 
     * @author b753
     * 
     */
    public interface IStateReceiver {
        public void initState();

        public boolean getState();
    }

    // public BatteryManager mBatteryManager;
    public BatteryTaskInfo mBatteryTaskInfo;
    public ProcessSettingManager mProcessSettingManager;

    private ServiceBinder myBinder = new ServiceBinder();
    // private SampleIdReceiver sampleIdReceiver;
    private BatteryChangedReceiver batteryChangedReceiver;
    private ScreenAndConChangedReceiver screenReceiver;
    private TelephonChangedReceiver telephonChangedReceiver;
    private AudioChangedReceiver audioChangedReceiver;
    private ConnectionChangeReceiver connectionChangeReceiver;
    private PackageChangedReceiver packageChangedReceiver;

    public ActionMapInfo mActionMapInfo = null;// 为了AIDL封装的
    public WhiteMapMapInfo mWhiteMapMapInfo = null;

    // public HashMap<String, ReceiverProcessInfo> actionMap = null;
    // public static HashMap<String, ProcessStatsInfo> whiteMap = null;
    public static ArrayList<ReceiverProcessInfo> compontList = null;

    public static boolean isServerRun = false;
    public boolean isRoot = false;
    public int simpleId = 1;

    private ArrayList<IStateReceiver> stateReceivers = new ArrayList<IStateReceiver>();

    public int curBatteryLevel = 0;

    public boolean isConnected = true;

    @Override
    public void onCreate() {
        Log.v(TAG, "onCreate");
        isRoot = ProcessSettingManager.isRooted();
        // startForeground(1, new Notification());
        super.onCreate();
        isServerRun = true;
        simpleId = getSiampleId();

        mBatteryTaskInfo = new BatteryTaskInfo();
        // analysisInfo = new NormalBatteryAlsInfo();

        mProcessSettingManager = new ProcessSettingManager();
        // mBatteryManager = new BatteryManager(this);

        // sampleIdReceiver = new SampleIdReceiver();
        audioChangedReceiver = new AudioChangedReceiver(this);
        telephonChangedReceiver = new TelephonChangedReceiver(this);
        batteryChangedReceiver = new BatteryChangedReceiver(this);
        screenReceiver = new ScreenAndConChangedReceiver(this);
        connectionChangeReceiver = new ConnectionChangeReceiver(this);
        packageChangedReceiver = new PackageChangedReceiver(this);

        SignalChangedModule sM = new SignalChangedModule(this);
        ProcessPowerModule pM = new ProcessPowerModule(this);
        NetWorkSampleMoudle nM = new NetWorkSampleMoudle(this);

        batteryChangedReceiver.registerSample(pM);
        batteryChangedReceiver.registerSample(nM);
        batteryChangedReceiver.registerSample(sM);

        IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
        filter.addDataScheme("package");

        registerReceiver(packageChangedReceiver, filter);
        registerReceiver(connectionChangeReceiver, new IntentFilter(
                ConnectivityManager.CONNECTIVITY_ACTION));
        registerReceiver(batteryChangedReceiver, new IntentFilter(
                Intent.ACTION_BATTERY_CHANGED));
        registerReceiver(screenReceiver, new IntentFilter(
                Intent.ACTION_SCREEN_ON));
        registerReceiver(screenReceiver, new IntentFilter(
                Intent.ACTION_SCREEN_OFF));
        registerReceiver(screenReceiver, new IntentFilter(
                Intent.ACTION_POWER_CONNECTED));
        registerReceiver(screenReceiver, new IntentFilter(
                Intent.ACTION_POWER_DISCONNECTED));
        // registerReceiver(sampleIdReceiver, new IntentFilter(
        // Constant.ACTION_SAMPLE_ID));

        stateReceivers.add(telephonChangedReceiver);
        stateReceivers.add(screenReceiver);
        stateReceivers.add(audioChangedReceiver);

        // get
        // if (mList == null) {
        // queryReceiverInfo();
        // }

        if (mActionMapInfo == null) {
            mActionMapInfo = new ActionMapInfo();
            getAcitonfromDB();
        }
        if (mWhiteMapMapInfo == null) {
            mWhiteMapMapInfo = new WhiteMapMapInfo();
            getWhiteListFromDB();
        }
        if (compontList == null || compontList.size() == 0) {
            queryReceiverInfo();
        }

        Log.v(TAG, "mActionMapInfo.size===" + mActionMapInfo.actionMap.size());
        Log.v(TAG,
                "mWhiteMapMapInfo.size===" + mWhiteMapMapInfo.whiteMap.size());
        screenReceiver.setIReciverCallback(this);

    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        Log.v(TAG, "onStart");
    }

    @Override
    public void onDestroy() {
        saveArgTimeToFile();
        unregisterReceiver(connectionChangeReceiver);
        unregisterReceiver(batteryChangedReceiver);
        unregisterReceiver(screenReceiver);
        unregisterReceiver(packageChangedReceiver);
        // unregisterReceiver(sampleIdReceiver);
        super.onDestroy();
        Log.v(TAG, "onDestroy");
    }

    private void saveArgTimeToFile() {
        mBatteryTaskInfo.saveDataToFile();
    }

    private void getAcitonfromDB() {
        Cursor cursor = getContentResolver().query(ActionTable.CONTENT_URI,
                null, null, null, null);
        Log.v(TAG, "getAcitonfromDB_cursor===" + cursor.getCount());
        if (null != cursor && cursor.getCount() > 0) {
            for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor
                    .moveToNext()) {
                ReceiverProcessInfo info = new ReceiverProcessInfo();
                info.setAppName(cursor.getString(cursor
                        .getColumnIndex(ActionTable.APPNAME)));
                info.setPackageName(cursor.getString(cursor
                        .getColumnIndex(ActionTable.PKG_NAME)));
                info.setProcessName(cursor.getString(cursor
                        .getColumnIndex(ActionTable.PROCESS_NAME)));
                info.setIsClose(cursor.getInt(cursor
                        .getColumnIndex(ActionTable.ACATION_TYPE)));
                mActionMapInfo.actionMap.put(info.packageName, info);
                Log.v(TAG, "key===" + info.processName);
                Log.v(TAG, "appName===" + info.appName);
            }
        }
        if (cursor != null) {
            cursor.close();
        }
    }

    private void getWhiteListFromDB() {
        Cursor cursor = getContentResolver().query(WhiteListTable.CONTENT_URI,
                null, null, null, null);
        Log.v(TAG, "White_cursor===" + cursor.getCount());
        if (null != cursor && cursor.getCount() > 0) {
            for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor
                    .moveToNext()) {
                ProcessStatsInfo info = new ProcessStatsInfo();
                info.setAppName(cursor.getString(cursor
                        .getColumnIndex(WhiteListTable.APP_NAME)));
                info.setPackageName(cursor.getString(cursor
                        .getColumnIndex(WhiteListTable.PKG_NAME)));
                info.setProcessName(cursor.getString(cursor
                        .getColumnIndex(WhiteListTable.PROCESS_NAME)));
                mWhiteMapMapInfo.whiteMap.put(info.packageName, info);
                Log.v(TAG, "key===" + info.processName);
                Log.v(TAG, "appName===" + info.appName);
            }
        }
        if (cursor != null) {
            cursor.close();
        }
    }

    public boolean isSample() {
        Log.v(TAG, "start_isSample");
        boolean isSample = true;
        for (int i = 0; i < stateReceivers.size(); i++) {
            if (!(stateReceivers.get(i).getState())) {
                isSample = false;
            }
        }
        Log.v(TAG, "isSample===" + isSample);
        return isSample;
    }

    /**
     * 初始化 isSreenOpend=false
     */
    public void initState() {
        for (int i = 0; i < stateReceivers.size(); i++) {
            stateReceivers.get(i).initState();
        }
    }

    public ProcessSettingManager getProcessManager() {
        return mProcessSettingManager;
    }

    public IBinder onBind(Intent intent) {
        return myBinder;
    }

    @Override
    public void executeCallback(int type) {
        switch (type) {
        case IReciverCallback.TYPE_SCREEN:
            List<RunningAppProcessInfo> runningInfo = ProcessSettingManager
                    .getRunProcess();

            if (isRoot) {
                Log.v(TAG, "executeCallback_isRoot");
                mProcessSettingManager.killProcess(runningInfo,
                        mActionMapInfo.actionMap);
                setCpuFreq();
            } else {
                Log.v(TAG, "executeCallback_noRoot");
                mProcessSettingManager.killProcessNoRoot(runningInfo,
                        mActionMapInfo.actionMap);
            }
            break;
        default:
            break;
        }
    }

    private void setCpuFreq() {
        PreferencesUtil util = PreferencesUtil.getInstance(App.mContext);
        boolean isCpuFreqSetting = util.getBoolean(Constant.KAY_ISCPU_FREP);
        if (isCpuFreqSetting) {
            CPUFreqSetting cpufreqSetting = new CPUFreqSetting();
            boolean isHaveUserSpace = util
                    .getBoolean(Constant.KAY_ISCPU_HAVE_USERSAPCE);
            if (isHaveUserSpace) {
                cpufreqSetting.setUserSpaceMod(CPUFreqSetting.TAG_POWERSAVE);
            } else {
                cpufreqSetting.setUserSpaceMod(CPUFreqSetting.TAG_USERSPACE);
            }
            util.putBoolean(Constant.KAY_ISCPU_FREP_STATE, true);
        }
    }

    public void inintAcitonMap() {
        if (mActionMapInfo.actionMap != null) {
            mActionMapInfo.actionMap.clear();
        }
        if (compontList != null) {
            compontList.clear();
        }
    }

    public ArrayList<ReceiverProcessInfo> queryReceiverInfo() {
        try {
            android.util.Log.v(TAG, "queryReceiverInfo");
            compontList = mProcessSettingManager
                    .getCompoentProcesslist("android.net.conn.CONNECTIVITY_CHANGE");
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
        return compontList;
    }

    public static void setReceiverInfo(ArrayList<ReceiverProcessInfo> list) {
        compontList = list;
    }

    public ArrayList<ReceiverProcessInfo> getReceiverInfo() {
        if (compontList == null) {
            compontList = queryReceiverInfo();
        }
        return compontList;
    }

    // public BatteryManager getBatteryManager() {
    // return mBatteryManager;
    // }

    public ProcessSettingManager getmProcessSettingManager() {
        return mProcessSettingManager;
    }

    public void addWhiteFromMap(ProcessStatsInfo info) {
        if (info != null) {
            mWhiteMapMapInfo.whiteMap.put(info.packageName, info);
        }
    }

    /**
     * 
     * @param key
     *            packageName
     */
    public void deleWhiteFromMap(String key) {
        mWhiteMapMapInfo.whiteMap.remove(key);
    }

    private int getSiampleId() {
        int id = PreferencesUtil.getInstance(App.mContext).getInt(
                Constant.SAMPLE_ID, 1);
        return id;
    }

    public int getCurBatteryLevel() {
        return curBatteryLevel;
    }

    public void setCurBatteryLevel(int curBatteryLevel) {
        this.curBatteryLevel = curBatteryLevel;
    }

    @Override
    public void setNetState() {
        // TODO Auto-generated method stub
    }

    public BaseBatteryAlsInfo getBatteryAlsInfo() {
        return mBatteryTaskInfo.getInfo(connectionChangeReceiver
                .getNetWorkState());
    }

    public ActionMapInfo getActionMap() {
        return mActionMapInfo;
    }

    public WhiteMapMapInfo getWhiteMap() {
        return mWhiteMapMapInfo;
    }

    public int getSimpleId() {
        return simpleId;
    }

    public class ServiceBinder extends IService.Stub {

        @Override
        public int getSimpleId() throws RemoteException {
            return simpleId;
        }

        @Override
        public int getCurBatteryLevel() throws RemoteException {
            return curBatteryLevel;
        }

        @Override
        public float getArgTimeM() throws RemoteException {
            Log.v(TAG, "getArgTimeM===" + getBatteryAlsInfo().getArgTimeM());
            return getBatteryAlsInfo().getArgTimeM();
        }

        @Override
        public WhiteMapMapInfo getWhiteMap() throws RemoteException {
            Log.v(TAG,
                    "mWhiteMapMapInfo.size==="
                            + mWhiteMapMapInfo.whiteMap.size());
            return mWhiteMapMapInfo;
        }

        @Override
        public ActionMapInfo getActionMap() throws RemoteException {
            Log.v(TAG,
                    "mActionMapInfo.size===" + mActionMapInfo.actionMap.size());
            return mActionMapInfo;
        }

        @Override
        public void setWhiteMap(WhiteMapMapInfo whiteMapInfo)
                throws RemoteException {
            mWhiteMapMapInfo = whiteMapInfo;
            Log.v(TAG, "setWhiteMap.size===" + mWhiteMapMapInfo.whiteMap.size());
        }

        @Override
        public void setActionMap(ActionMapInfo actionMapInfo)
                throws RemoteException {
            mActionMapInfo = actionMapInfo;
            Log.v(TAG, "setActionMap.size===" + mActionMapInfo.actionMap.size());
        }

        @Override
        public void setSimpleId(int simpleId) throws RemoteException {
            BatteryManagerService.this.simpleId = simpleId;
            Log.v(TAG, "setSimpleId===" + simpleId);
        }
    }
}
